package com.wstuo.common.tools.service;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.mail.search.AndTerm;
import javax.mail.search.ComparisonTerm;
import javax.mail.search.SearchTerm;
import javax.mail.search.SentDateTerm;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.wstuo.common.config.attachment.dao.IAttachmentDAO;
import com.wstuo.common.config.attachment.entity.Attachment;
import com.wstuo.common.exchange.IWebDavService;
import com.wstuo.common.tools.dao.IEmailDAO;
import com.wstuo.common.tools.dto.EmailConnectionDTO;
import com.wstuo.common.tools.dto.EmailDTO;
import com.wstuo.common.tools.dto.EmailMessageDTO;
import com.wstuo.common.tools.dto.EmailMessageQueryDTO;
import com.wstuo.common.tools.dto.EmailServerDTO;
import com.wstuo.common.tools.dto.MessageConsumerDTO;
import com.wstuo.common.tools.entity.EmailMessage;
import com.wstuo.common.tools.util.FilterXssUtils;
import com.wstuo.common.dto.PageDTO;
import com.wstuo.common.exception.ApplicationException;
import com.wstuo.common.security.dao.IUserDAO;
import com.wstuo.common.security.entity.User;
import com.wstuo.common.security.service.IUserInfoService;
import com.wstuo.common.security.utils.AppConfigUtils;
import com.wstuo.common.util.StringUtils;
import com.wstuo.common.util.TimeUtils;

/**
 * 邮件服务Service
 * 
 * @author brain date 2010 11/8
 * **/
public class EmailService implements IEmailService {
	public static final int SUCESS_CONN_ALL = 0; // 服务发送邮箱测试成功
	public static final int FAIL_CONN_POP3 = 1; // 服务邮箱测试失败
	public static final int FAIL_CONN_SMTP = 2; // 发送邮箱测试失败
	public static final int FAIL_CONN_POP3ANDSMTP = 3; // 服务和发送邮箱测试失败
	
	public static final String MAILTYPE = "text/html;charset=GBK";
	public static final String MULTIPARTTYPE_MIXED = "mixed";
	private static final String ATTACHMENT_PATH=AppConfigUtils.getInstance().getAttachmentPath();
	private final static Logger LOGGER = Logger.getLogger(EmailService.class);
	@Autowired
	private IEmailDAO emailDAO;
	@Autowired
	private IAttachmentDAO attachmentDAO;
	@Autowired
	private IUserDAO userDAO;
	@Autowired
	private IUserInfoService userInfoService;
	@Autowired
	private IEmailServerService emailServerService;
	@Autowired
	private IWebDavService webDavService;

	private Session session;
	private String saveAttachPath; // 附件下载后的存放目录
	private List<Attachment> attachments = new ArrayList<Attachment>(); // 附件
	private StringBuffer bodytext = new StringBuffer(); // 存放邮件内容
	private String saveDir; // 图片本地路径
	private StringBuffer cutImgUrl= new StringBuffer();//截图附件路径

	public void setAttachPath(String attachpath) {
		this.saveAttachPath = attachpath;
	}

	public String getAttachPath() {
		return saveAttachPath;
	}

	public Boolean scanEmailMessagesByUserService(EmailConnectionDTO emailConnectionDto) {
		boolean result = false;
		if (emailConnectionDto.getUsername() == null) {
			EmailServerDTO dto = emailServerService.findEmail();
			setEmailConnectionDto(emailConnectionDto, dto);
		}
		int testErrorEncode = emailConnTest(emailConnectionDto);
		if (testErrorEncode == 0) {
			result = saveReceiveMessages(emailConnectionDto);
		} else {
			result = false;
		}
		return result;
	}

	/**
	 * set EmailConnectionDTO
	 * 
	 * @param emailConnectionDto
	 * @param dto
	 * @return EmailConnectionDTO
	 */
	private EmailConnectionDTO setEmailConnectionDto(EmailConnectionDTO emailConnectionDto, EmailServerDTO dto) {
		try {
			if(StringUtils.hasText(dto.getPop3ServerAddress())&&StringUtils.hasText(dto.getPop3ServerPort())){
				emailConnectionDto.setPop3host(dto.getPop3ServerAddress());
				emailConnectionDto.setPop3port(Integer.parseInt(dto.getPop3ServerPort()));
			}
			emailConnectionDto.setSmtphost(dto.getSmtpServerAddress());
			emailConnectionDto.setSmtpport(Integer.parseInt(dto.getSmtpServerPort()));
			emailConnectionDto.setUsername(dto.getUserName());
			emailConnectionDto.setPassword(dto.getPassword());
		} catch (Exception e) {
			throw new ApplicationException("ERROR_SENDEMAILMESSAGE\n" + e, e);
		}
		return emailConnectionDto;
	}

	/**
	 * set Properties
	 * 
	 * @return Properties
	 */
	private Properties setEmailConnTestProperties(String smtphost, Integer smtpport) {
		Properties pros = new Properties();
		pros.setProperty("mail.transport.protocol", "smtp");
		pros.setProperty("mail.smtp.auth", "true");
		if (StringUtils.hasText(smtphost)) {
			pros.setProperty("mail.host", smtphost);
		} else {
			pros.setProperty("mail.host", "");
		}
		pros.setProperty("mail.smtp.port", String.valueOf(smtpport));
		return pros;
	}

	/**
	 * 发送邮件连接测试
	 * 
	 * @param dto
	 *            邮件连接帐号信息DTO
	 * @return boolean
	 */
	public boolean sendEmailConnTest(final EmailConnectionDTO dto) {
		boolean blo = false;
		if(dto!=null && dto.getSmtphost()!=null &&dto.getSmtpport()!=null){
			Properties pros = setEmailConnTestProperties(dto.getSmtphost(), dto.getSmtpport());
			session = Session.getInstance(pros, new Authenticator() {
				protected PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication(dto.getUsername(), dto.getPassword());
				}
			});
			session.setDebug(false);
			try {
				Transport tran = session.getTransport("smtp");
				tran.connect();
				blo = tran.isConnected();
			} catch (MessagingException e) {
				LOGGER.error(e);
				blo = false;
			}
		}
		return blo;
	}

	/**
	 * set Properties
	 * 
	 * @param pop3host
	 * @param pop3port
	 * @return Properties
	 */
	private Properties setPopProperties(String pop3host, Integer pop3port) {
		Properties props = new Properties();
		if (StringUtils.hasText(pop3host)) {
			props.put("mail.pop3.host", pop3host);
		}
		if (pop3port != 0) {
			props.put("mail.pop3.port", pop3port);
		}
		props.put("mail.pop3.auth", "true");
		return props;
	}

	/**
	 * 接收邮件连接测试
	 * 
	 * @param dto
	 *            邮件连接帐号信息DTO
	 * @return boolean
	 */
	public boolean receiveEmailConnTest(final EmailConnectionDTO dto) {
		boolean blo = false;
		if(dto!=null && dto.getPop3host()!=null && dto.getPop3port()!=null){
			Properties props = setPopProperties(dto.getPop3host(), dto.getPop3port());
			Session session = Session.getInstance(props, null);
			Store store = null;
			try {
				store = session.getStore("pop3");
				store.connect(dto.getUsername(), dto.getPassword());
				Folder folder = store.getFolder("INBOX");
				folder.open(Folder.READ_ONLY);
				blo = true;
			} catch (Exception e) {
				LOGGER.error(e);
				blo = false;
			} finally {
				if (null != store && store.isConnected()) {
					try {
						store.close();
					} catch (MessagingException e) {
						LOGGER.error(e);
					}
				}
			}
		}
		return blo;
	}

	/**
	 * 邮件连接测试
	 * 
	 * @param dto
	 *            邮件连接帐号信息DTO
	 * @return int
	 */
	public int emailConnTest(EmailConnectionDTO dto) {
		boolean pop3result = false;
		boolean stmpresult = false;
		int result = SUCESS_CONN_ALL;
		if(StringUtils.hasText(dto.getPop3host())&&dto.getPop3port()!=null){
			pop3result = this.receiveEmailConnTest(dto);// 接收邮箱连接测试结果
			if (!pop3result) {
				result = FAIL_CONN_POP3;// 接收邮箱连接失败
			}
		}else if(StringUtils.hasText(dto.getSmtphost())&&dto.getSmtpport()!=null){
			stmpresult = this.sendEmailConnTest(dto);// 发送邮箱连接测试结果
			if (!stmpresult) {
				result = FAIL_CONN_SMTP;// 发送邮箱连接失败
			}
		}else{
			result=FAIL_CONN_POP3ANDSMTP;
		}
		return result;
	}

	/**
	 * 
	 * @param smtphost
	 * @param smtpport
	 * @return
	 */
	private Properties setSmtpConnectionProperties(String smtphost, int smtpport) {
		Properties pros = new Properties();
		if (smtphost.indexOf("smtp.gmail.com") >= 0) {
			pros.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
			pros.setProperty("mail.smtp.socketFactory.fallback", "false");
			pros.setProperty("mail.smtp.port", "465");
			pros.setProperty("mail.smtp.socketFactory.port", "465");
		}
		pros.setProperty("mail.transport.protocol", "smtp");
		pros.setProperty("mail.smtp.auth", "true");
		pros.setProperty("mail.host", smtphost);
		pros.setProperty("mail.smtp.port", String.valueOf(smtpport));
		return pros;
	}

	/**
	 * 邮件连接创建初始化
	 */
	public void mailSmtpConnection() {
		EmailServerDTO emailServerDTO = emailServerService.findEmail();
		if (emailServerDTO != null) {
			final EmailConnectionDTO emailConnectionDto = new EmailConnectionDTO();
			setEmailConnectionDto(emailConnectionDto, emailServerDTO);

			if ((emailConnectionDto.getSmtphost() != null) && (emailConnectionDto.getUsername() != null) && (emailConnectionDto.getPassword() != null)) {
				Properties pros = setSmtpConnectionProperties(emailConnectionDto.getSmtphost(), emailConnectionDto.getSmtpport());
				session = Session.getInstance(pros, new Authenticator() {
					protected PasswordAuthentication getPasswordAuthentication() {
						return new PasswordAuthentication(emailConnectionDto.getUsername(), emailConnectionDto.getPassword());
					}
				});
				session.setDebug(false);
			} else {
				throw new ApplicationException("ERROR_EMAIL_ACCOUNT_ERROR\n");
			}
		}
	}

	/**
	 * 连接发送服务器(需要直接传连接邮件服务器参数)
	 * 
	 * @param emailConnectionDto
	 */
	public void mailSmtpConnection(final EmailConnectionDTO emailConnectionDto) {
		if ((emailConnectionDto.getSmtphost() != null) && (emailConnectionDto.getUsername() != null) && (emailConnectionDto.getPassword() != null)) {
			Properties pros = setSmtpConnectionProperties(emailConnectionDto.getSmtphost(), emailConnectionDto.getSmtpport());
			session = Session.getInstance(pros, new Authenticator() {
				protected PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication(emailConnectionDto.getUsername(), emailConnectionDto.getPassword());
				}
			});
			session.setDebug(false);
		} else {
			throw new ApplicationException("ERROR_EMAIL_ACCOUNT_ERROR\n");
		}
	}

	/**
	 * 对接收者邮件地址进行处理
	 * 
	 * @param dto
	 * @return EmailDTO
	 */
	private EmailDTO processingRecipientEmailAddress(EmailDTO dto) {
		if (dto.getReceiveAddress() != null) {
			dto.setReceiveAddress(dto.getReceiveAddress().replace(",", ";"));
			String[] receiveAddress = dto.getReceiveAddress().split(";");
			if (receiveAddress != null && receiveAddress.length > 0) {
				if (dto.getTo() != null) {
					for (String address : receiveAddress) {
						dto.getTo().add(address);
					}
				} else {
					List<String> emails = new ArrayList<String>();
					for (String address : receiveAddress) {
						emails.add(address);
					}
					dto.setTo(emails);
				}
			}
		}
		return dto;
	}

	/**
	 * set MimeMultipart
	 * 
	 * @param multipartType
	 * @throws MessagingException
	 */
	private MimeMultipart setMimeMultipart(String content) throws MessagingException {
		MimeMultipart multipart = new MimeMultipart(MULTIPARTTYPE_MIXED);
		BodyPart msgBodyPart = new MimeBodyPart();
		multipart.addBodyPart(msgBodyPart);
		msgBodyPart.setContent(content, MAILTYPE);
		return multipart;
	}

	/**
	 * transport Send Internet Address
	 * 
	 * @param dto
	 * @param msg
	 * @return MimeMessage
	 * @throws MessagingException
	 */
	private MimeMessage transportSendInternetAddress(EmailDTO dto, MimeMessage msg) throws MessagingException {
		InternetAddress[] tos = new InternetAddress[dto.getTo().size()];
		// SendEmail
		for (int i = 0, len = dto.getTo().size(); i < len; i++) {
			Address address = null;
			try {
				// Set recipient address
				address = new InternetAddress(dto.getTo().get(i));
				tos[i] = new InternetAddress(dto.getTo().get(i));
				msg.setRecipient(RecipientType.TO, address);
				// If addr as xxx@qq.com && xxx@qq.com is not exist,then throw Excption 550 Mailbox not found...
				msg.setSubject(MimeUtility.encodeText(msg.getSubject(), "UTF-8", "B"));
				Transport.send(msg);
				
			} catch (Exception e) {
				LOGGER.error("try send '" + address + "' error");
				continue;
			}
		}
		msg.setRecipients(RecipientType.TO, tos);
		return msg;
	}

	/**
	 * join Reports
	 * 
	 * @param multipart
	 * @param files
	 * @param msg
	 * @return MimeMessage
	 * @throws MessagingException
	 * @throws UnsupportedEncodingException
	 */
	private MimeMessage joinReports(MimeMultipart multipart, List<File> files, MimeMessage msg) throws MessagingException, UnsupportedEncodingException {
		if (files != null && files.size() > 0) {// 加入报表文件
			BodyPart attBodyPart;
			DataSource ds;
			for (File file : files) {
				attBodyPart = new MimeBodyPart();
				ds = new FileDataSource(file);
				attBodyPart.setDataHandler(new DataHandler(ds));
				attBodyPart.setFileName(MimeUtility.encodeText(ds.getName()));
				multipart.addBodyPart(attBodyPart);
			}
			msg.setContent(multipart);
		}
		return msg;
	}

	/**
	 * 普通邮件服务器发送邮件模式(包含加入报表)
	 * 
	 * @param emailServerDTO
	 * @param dto
	 * @param files
	 * @return boolean
	 */
	@Transactional
	private boolean normalTransmissionMode(EmailServerDTO emailServerDTO, EmailDTO dto, List<File> files) {
		boolean result = false;
		this.mailSmtpConnection();// 邮件连接
		dto.setFrom(emailServerDTO.getUserName());// 设置发件人
		try {
			if (dto.getTo().size() > 0) {
				MimeMessage msg = new MimeMessage(session);
				msg = setMimeMessage(msg, dto, emailServerDTO);
				// set MimeMultipart
				MimeMultipart multipart = setMimeMultipart(dto.getContent());
				// join Reports
				msg = joinReports(multipart, files, msg);
				msg = transportSendInternetAddress(dto, msg);
				EmailMessage emailMessage = mime2Entity(msg, "OUTBOX", dto.getFrom());// 转成邮件实体
				saveEmailMessages(emailMessage);// 保存到数据
			}
			result = true;
		} catch (Exception e) {
			result = false;
			LOGGER.error(e);
		}
		return result;
	}

	/**
	 * 邮件发送并保存到数据库中作为已发送的邮件
	 * 
	 * @param dto
	 * @param files
	 */
	@Transactional
	public boolean sendMail(EmailDTO dto, List<File> files) {
		EmailServerDTO emailServerDTO = emailServerService.findEmail();
		boolean result = false;
		if (emailServerDTO != null) {
			// 对接收者邮件地址进行处理 start
			dto = processingRecipientEmailAddress(dto);
			if (dto.getTo().size() > 0 && StringUtils.hasText(emailServerDTO.getEmailType())) {
				if (emailServerDTO.getEmailType().equals("exchange")) {// exchange邮件服务器
					dto.setFrom(emailServerDTO.getExchangeUserName());// 设置发件人
					result = webDavService.sendEmail(dto);
				} else {// 普通邮件服务器
					result = normalTransmissionMode(emailServerDTO, dto, files);
				}
			}

		}
		return result;
	}

	/**
	 * set MimeMessage
	 * 
	 * @param dto
	 * @param msg
	 * @return MimeMessage
	 * @throws MessagingException
	 * @throws UnsupportedEncodingException
	 */
	private MimeMessage setMimeMessageContent(EmailDTO dto, MimeMessage msg) throws MessagingException, UnsupportedEncodingException {
		if ((null == dto.getPicPath()) && (null == dto.getAffachmentPath())) {
			msg.setContent(dto.getContent().replace("$", "&nbsp;"), MAILTYPE);
		} else {
			MimeMultipart multipart = new MimeMultipart(MULTIPARTTYPE_MIXED);
			BodyPart msgBodyPart = new MimeBodyPart();
			multipart.addBodyPart(msgBodyPart);
			if (dto.getAffachmentPath() != null) {
				BodyPart attBodyPart;
				DataSource ds;
				for (int i = 0; i < dto.getAffachmentPath().length; i++) {
					attBodyPart = new MimeBodyPart();
					ds = new FileDataSource(new File(dto.getAffachmentPath()[i]));
					attBodyPart.setDataHandler(new DataHandler(ds));
					attBodyPart.setFileName(MimeUtility.encodeText(ds.getName()));
					multipart.addBodyPart(attBodyPart);
				}
				msg.setContent(multipart);
			}
			msg.setContent(dto.getContent().replace("$", "&nbsp;"), MAILTYPE);
		}
		return msg;
	}

	/**
	 * set MimeMessage
	 * 
	 * @param msg
	 * @param dto
	 * @param emailServerDTO
	 * @return MimeMessage
	 * @throws MessagingException
	 * @throws UnsupportedEncodingException
	 */
	private MimeMessage setMimeMessage(MimeMessage msg, EmailDTO dto, EmailServerDTO emailServerDTO) throws MessagingException, UnsupportedEncodingException {
		// 设置发件人姓名(姓名<email@email.com>)
		if (emailServerDTO.getPersonal() != null) {
			msg.setFrom(new InternetAddress(dto.getFrom(), MimeUtility.encodeText(emailServerDTO.getPersonal(), "UTF-8", "b")));
		} else {
			msg.setFrom(new InternetAddress(dto.getFrom()));
		}
		msg.setSubject(FilterXssUtils.string_decode(dto.getSubject()));
		msg.setSentDate(new Date());
		return msg;
	}

	/**
	 * 普通邮件服务器发送邮件模式
	 * 
	 * @param emailServerDTO
	 * @param dto
	 * @return boolean
	 */
	private boolean normalTransmissionMode(EmailServerDTO emailServerDTO, EmailDTO dto) {
		boolean result = false;
		this.mailSmtpConnection();// 邮件连接
		try {
			// 发件人邮件地址
			if (StringUtils.hasText(emailServerDTO.getPersonalEmailAddress())) {
				dto.setFrom(emailServerDTO.getPersonalEmailAddress());
			} else {
				dto.setFrom(emailServerDTO.getUserName());// 设置发件人
			}
			MimeMessage msg = new MimeMessage(session);
			msg = setMimeMessage(msg, dto, emailServerDTO);
			msg = setMimeMessageContent(dto, msg);
			msg = transportSendInternetAddress(dto, msg);
			EmailMessage emailMessage = mime2Entity(msg, "OUTBOX", dto.getFrom());// 转成邮件实体
			emailMessage.setModuleCode(dto.getModuleCode());
			saveEmailMessages(emailMessage);// 保存到数据
			result = true;
		} catch (Exception e) {
			result = false;
			LOGGER.error(e);
		}
		return result;
	}
	
	/**
	 * 邮件发送
	 * @param messageConsumerDTO
	 * @return boolean
	 */
	@Transactional
	public void sendMail(MessageConsumerDTO messageConsumerDTO) {
		EmailDTO emailDTO = new EmailDTO(); 
		emailDTO.setSubject(messageConsumerDTO.getSubject());
		emailDTO.setContent(messageConsumerDTO.getContent());
		emailDTO.setModuleCode(messageConsumerDTO.getModule());
		List<String> emails = new ArrayList<String>();
		emails.addAll(messageConsumerDTO.getTo());
		emailDTO.setTo(emails);
		sendMail(emailDTO);
	}

	/**
	 * 邮件发送并保存到数据库中作为已发送的邮件
	 * 
	 * @param dto
	 *            EmailDTO
	 * @return boolean
	 */
	@Transactional
	public boolean sendMail(EmailDTO dto) {
		boolean result = false;
		EmailServerDTO emailServerDTO = emailServerService.findEmail();
		if ( emailServerDTO != null && dto != null) {
			// 对接收者邮件地址进行处理
			dto = processingRecipientEmailAddress(dto);
			int type = emailServerDTO.getServerEmailType() ;
			// 如果存在接收地址
			if (dto.getTo().size() > 0 && type != EmailServerDTO.EMAIL_TYPE_NONE ) {
				if ( type == EmailServerDTO.EMAIL_TYPE_EXCHANGE ) {// exchange邮件服务器
					dto.setFrom(emailServerDTO.getExchangeUserName());// 设置发件人
					result = webDavService.sendEmail(dto);
				} else if( type == EmailServerDTO.EMAIL_TYPE_NORMAL ) {// 普通邮件服务器
					result = normalTransmissionMode(emailServerDTO, dto);
				}
			}
		}
		return result;
	}

	/**
	 * 邮件发送(不需要保存到数据库)
	 * 
	 * @param dto
	 *            EmailDTO
	 * @param emailConnectionDto
	 *            EmailConnectionDTO
	 * @return boolean
	 */
	public boolean sendMail(EmailDTO dto, EmailConnectionDTO emailConnectionDto) {
		EmailServerDTO emailServerDTO = emailServerService.findEmail();
		boolean result = false;
		if (emailConnectionDto != null) {
			dto.setFrom(emailConnectionDto.getUsername());
			this.mailSmtpConnection(emailConnectionDto);
		}
		// 对接收者邮件地址进行处理
		dto = processingRecipientEmailAddress(dto);
		try {
			MimeMessage msg = new MimeMessage(session);
			msg = setMimeMessage(msg, dto, emailServerDTO);
			msg = setMimeMessageContent(dto, msg);
			transportSendInternetAddress(dto, msg);
			result = true;
		} catch (Exception e) {
			result = false;
			LOGGER.error(e);
		}
		return result;
	}

	/**
	 * 邮件发送(不需要再转换邮箱地址)
	 * 
	 * @param dto
	 *            EmailDTO
	 * @param emailConnectionDto
	 *            EmailConnectionDTO
	 * @param type
	 * @return boolean
	 */
	public boolean sendMail(EmailDTO dto, EmailConnectionDTO emailConnectionDto, String type) {
		boolean result = false;
		if (emailConnectionDto != null) {
			dto.setFrom(emailConnectionDto.getUsername());
			this.mailSmtpConnection(emailConnectionDto);
		}
		try {
			if (dto != null) {
				MimeMessage msg = new MimeMessage(session);
				msg.setFrom(new InternetAddress(dto.getFrom()));
				msg.setSubject(dto.getSubject());
				msg.setSentDate(new Date());
				msg = setMimeMessageContent(dto, msg);
				transportSendInternetAddress(dto, msg);
				result = true;
			}

		} catch (Exception e) {
			LOGGER.error(e);
			result = false;
		}
		return result;
	}

	/**
	 * set EamilMessage PageDTO
	 * 
	 * @param messages
	 * @param page1
	 * @param limit
	 * @return PageDTO
	 */
	private PageDTO setEamilMessagePageDTO(Message[] messages, int page1, int limit) {
		PageDTO page = new PageDTO();
		List<EmailDTO> dtos = new ArrayList<EmailDTO>();
		int totalSize = messages.length;
		int start = (page1 - 1) * limit;
		// int end=0;
		int end = (limit * page1) - 1;
		if (end >= totalSize) {
			end = totalSize - 1;
		}
		for (int i = start; i <= end; i++) {
			MimeMessage message = (MimeMessage) messages[i];
			dtos.add(entity2Dto(message));
		}
		page.setTotalSize(totalSize);
		page.setData(dtos);
		return page;
	}

	/**
	 * 读取邮件收信箱信
	 * 
	 * @param dto
	 *            EmailConnectionDTO
	 * @param page1
	 * @param limit
	 * @return PageDTO
	 */
	public PageDTO getEamilMessage(EmailConnectionDTO dto, int page1, int limit) {
		Properties props = setPopProperties(dto.getPop3host(), dto.getPop3port());
		props.put("mail.mime.base64.ignoreerrors", "true");
		Session session = Session.getInstance(props, null);
		Store store = null;
		Message[] messages;
		PageDTO page = null;
		try {
			store = session.getStore("pop3");
			store.connect(dto.getUsername(), dto.getPassword());
			Folder folder = store.getFolder("INBOX");
			folder.open(Folder.READ_ONLY);
			messages = reverse(folder.getMessages());
			page = setEamilMessagePageDTO(messages, page1, limit);
		} catch (Exception e) {
			LOGGER.error(e);
		} finally {
			if (null != store && store.isConnected()) {
				try {
					store.close();
				} catch (MessagingException e) {
					LOGGER.error(e);
				}
			}
		}
		return page;
	}

	/**
	 * 反转
	 * 
	 * @param data
	 * @return Message[]
	 */
	private static Message[] reverse(Message[] data) {
		int length = data.length;
		Message temp = null;
		for (int i = 0; i < (length / 2); i++) {
			temp = data[i];
			data[i] = data[length - 1 - i];
			data[length - 1 - i] = temp;
		}
		return data;
	}

	/**
	 * 读取到的邮件信息转成DTO
	 * 
	 * @param message
	 *            邮件信息内容
	 * @return EmailDTO
	 */
	private EmailDTO entity2Dto(MimeMessage message) {
		EmailDTO dto = new EmailDTO();
		try {
			this.getMailContent(message);
			dto.setContent(this.getBodyText());
			dto.setMailId(message.getMessageNumber());
			dto.setSendDate(TimeUtils.format(message.getSentDate(),TimeUtils.DATETIME_PATTERN));
			dto.setDescription(message.getDescription());
			String subject = getSubject(message);
			dto.setSubject(subject);
			dto.setFromEmail(this.getFrom(message));
		} catch (Exception e) {
			LOGGER.error(e);
		}
		return dto;
	}

	/**
	 * 读取到的邮件信息转成DTO
	 * 
	 * @param message
	 *            邮件信息内容
	 * @return EmailMessageDTO
	 */
	@Transactional
	private EmailMessageDTO entity2Dto(EmailMessage emailMessage) {
		EmailMessageDTO dto = new EmailMessageDTO();
		try {
			BeanUtils.copyProperties(dto, emailMessage);
			List<Attachment> attrs = emailMessage.getAttachment();
			if ((attrs != null) && (attrs.size() > 0)) {
				dto.setAffachment(attrs);
			}
		} catch (Exception e) {
			LOGGER.error(e);
		}
		return dto;
	}

	/**
	 * set EmailMessage Info By FolderName
	 * 
	 * @param em
	 * @param message
	 * @param folderName
	 * @param userName
	 * @return EmailMessage
	 * @throws Exception
	 */
	private EmailMessage setEmailMessageInfoByFolderName(EmailMessage em, MimeMessage message, String folderName, String userName) throws Exception {
		userName = "<" + userName + ">";
		if (folderName.equals("INBOX")) {
			em.setFolderName("INBOX");
			em.setReceiveDate(message.getSentDate());
			em.setFromUser(this.getFrom(message));
			em.setToUser(userName);
		} else {
			em.setFolderName("OUTBOX");
			em.setToUser(this.getMailAddress(message, "TO"));
			em.setCc(this.getMailAddress(message, "CC"));
			em.setBcc(this.getMailAddress(message, "BCC"));
			em.setSendDate(new Date());
			em.setFromUser(this.getFrom(message));
		}
		return em;
	}

	/**
	 * set EmailMessage Attachment
	 * 
	 * @param em
	 * @param message
	 * @return EmailMessage
	 * @throws Exception
	 */
	private EmailMessage setEmailMessageAttachment(EmailMessage em, MimeMessage message) throws Exception {
		if (isContainAttach((Part) message)) {
			String fileFolder = TimeUtils.format(new Date(),FILENAME_PATTERN);
			saveDir = ATTACHMENT_PATH + File.separator + fileFolder;
			// 如果目录不存在则创建
			if (!(new File(saveDir).isDirectory())) {
				new File(saveDir).mkdirs();
			}
			attachments.clear();
			this.setAttachPath(saveDir);
			em.setMailPath(saveDir);
			this.saveAttachMent((Part) message);
			em.setAttachment(attachments);
		}
		return em;
	}

	/**
	 * 读取邮件信息转成Entity
	 * 
	 * @param emessage
	 *            邮件信息内容
	 * @param folderName
	 * @param userName
	 * @return EmailMessage
	 */
	private EmailMessage mime2Entity(MimeMessage message, String folderName, String userName) {
		EmailMessage em = new EmailMessage();
		try {
			em.setSubject(message.getSubject());
			getMailContent(message);
			
			em.setDescription(message.getDescription());
			em = setEmailMessageInfoByFolderName(em, message, folderName, userName);
			em = setEmailMessageAttachment(em, message);
			List<Attachment> atts=null;
			if (em.getAttachment() != null) {
				atts = new ArrayList<Attachment>();
				cutImgUrl= new StringBuffer();
				for (int i = 0; i < em.getAttachment().size(); i++) {
					Attachment attr = em.getAttachment().get(i);
					attr.setType("itsm.request");
					attachmentDAO.save(attr);
					if("Screenshot.png".equals(attr.getAttachmentName())){
						cutImgUrl.append("attachment!download.action?downloadAttachmentId="+attr.getAid()+"@");
					}else
						atts.add(attr);
				}
			}
			em.setAttachment(atts);
			em.setContent(getBodyText().replaceAll("<script", "&lt;script").replaceAll("</script?", "&lt;/script&gt;")); // 内容'
		} catch (Exception e) {
			LOGGER.error(e);
		}
		return em;
	}

	/**
	 * 获得邮件正文内容
	 * 
	 * @return String
	 */
	public String getBodyText() {
/*		if(bodytext!=null && bodytext.indexOf("src=\"cid:")>-1){
			bodytext=replaceAll(bodytext,"src=\"cid:", "src=\""+saveDir+File.separator);
		}*/
		if(bodytext!=null){
			try {
				bodytext=replaceAll(bodytext);
			} catch (Exception e) {
				e.printStackTrace();
				LOGGER.error(e);
			}
		}
		return bodytext!=null?bodytext.toString():"";
	}
	public StringBuffer replaceAll(StringBuffer sb){
		int start=sb.indexOf("<img");
		if(start>-1){
			int sLen="<img".length();
			int eLen=">".length();
			int end=0;
			String[] urls=cutImgUrl.toString().split("@");
			int num=urls.length;
			while(start>-1){
				end=sb.indexOf(">",start+sLen);
				if(!sb.substring(start, end+eLen).contains("src=\"http")){
					num--;
					if(num<0)break;
					sb.delete(start,end+eLen);
					String img= "<img src=\""+urls[num]+"\" />";
					sb.insert(start,img);
					start=sb.indexOf("<img",start+img.length());
				}else{
					break;
				}
			}
		}
		return sb;
	}
/*	public static void main(String[] args) {
		StringBuffer sb =new StringBuffer("<div>dsfsdfsdfsdf<img src=\"cid:2F02F904@0B4D5028.94347555\"" +
				" style=\"width: 1153px; height: 615px;\"/>dsfsdfsdfsdfsdf</div>" +
				"<span><img src=\"dfdf\" style=\"widthdsfdfd\"/></span>");
		System.err.println(replaceAll(sb));
	}*/
	/**
	 * 内容赋值
	 * 
	 * @param charset
	 * @param part
	 * @return String
	 * @throws IOException
	 * @throws MessagingException
	 */
	private String setContent(String charset, Part part) throws IOException, MessagingException {
		InputStream is = part.getInputStream();
		byte[] bs = new byte[is.available()];
		is.read(bs);
		String content = (new String(bs, charset)).trim();
		return content;
	}

	/**
	 * 解析邮件，把得到的邮件内容保存到StringBuffer对象中，解析邮件 主要是根据MimeType类型的不同执行不同的操作， 一步一步的解析
	 * 
	 * @param part
	 * @throws Exception
	 */
	@Transactional
	private void getMailContent(Part part) throws Exception {
		bodytext = new StringBuffer();
		String contenttype = part.getContentType();
		if (contenttype.indexOf("unicode-1-1-utf-7") == -1) {// 编码为日文的暂不做处理
			boolean conname = getConname(contenttype);
			if (part.isMimeType("text/plain") && !conname) {
				String content = getContentByMimeTypeTextPlain(contenttype, part);
				bodytext.append(content);
			} else if (part.isMimeType("text/html") && !conname) {
				try {
					String content = getContentByMimeTypeTextHtml(contenttype, part);
					bodytext.append(content);
				} catch (Exception e) {
					LOGGER.debug("GBK ERROR");
				}
			} else if (part.isMimeType("multipart/*")) {
				Multipart multipart = (Multipart) part.getContent();
				getMultipartMimeTypeMailContent(multipart.getBodyPart(0));
			} else if (part.isMimeType("message/rfc822")) {
				getMailContent((Part) part.getContent());
			}
		}
	}

	/**
	 * get Content
	 * 
	 * @param contenttype
	 * @param part
	 * @return String
	 * @throws IOException
	 * @throws MessagingException
	 */
	private String getContentByMimeTypeTextPlain(String contenttype, Part part) throws IOException, MessagingException {
		String content = null;
		try {
			content = (String) part.getContent();
		} catch (Exception ex) {
			String charset = contenttype.substring(contenttype.indexOf("=") + 1);
			content = setContent(charset, part);
		}
		return content;
	}

	/**
	 * get Content
	 * 
	 * @param contenttype
	 * @param part
	 * @return String
	 * @throws IOException
	 * @throws MessagingException
	 */
	private String getContentByMimeTypeTextHtml(String contenttype, Part part) throws IOException, MessagingException {
		String content = (String) part.getContent().toString();
		if (contenttype.indexOf("charset") < 0) {
			content = setContent("GBK", part);
		}
		return content;
	}

	/**
	 * get conname
	 * 
	 * @param contenttype
	 * @return boolean
	 */
	private boolean getConname(String contenttype) {
		int nameindex = contenttype.indexOf("name");
		boolean conname = false;
		if (nameindex != -1) {
			conname = true;
		}
		return conname;
	}

	/**
	 * 获取邮件内容
	 * 
	 * @param part
	 * @throws Exception
	 */
	@Transactional
	private void getMultipartMimeTypeMailContent(Part part) throws Exception {
		bodytext = new StringBuffer();
		String contenttype = part.getContentType();
		boolean conname = getConname(contenttype);
		if (part.isMimeType("text/plain") && !conname) {
			String content = getContentByMimeTypeTextPlain(contenttype, part);
			bodytext.append(content);
		} else if (part.isMimeType("text/html") && !conname) {
			String content = getContentByMimeTypeTextHtml(contenttype, part);
			bodytext.append(content);
		} else if (part.isMimeType("multipart/*")) {
			Multipart multipart = (Multipart) part.getContent();
			int counts = multipart.getCount();
			for (int i = 0; i < counts; i++) {
				getMultipartMimeTypeMailContent(multipart.getBodyPart(i));
			}
		} else if (part.isMimeType("message/rfc822")) {
			getMailContent((Part) part.getContent());
		}
	}

	/**
	 * 获得发件人的地址和姓名
	 * 
	 * @param message
	 * @return String
	 * @exception Exception
	 */
	private String getFrom(MimeMessage message) throws Exception {
		InternetAddress[] address = (InternetAddress[]) message.getFrom();
		String from = address[0].getAddress();
		if (from == null) {
			from = "";
		}
		String personal = address[0].getPersonal();
		if (personal == null) {
			personal = "";
		}
		String fromaddr = personal + "<" + from + ">";
		return fromaddr;
	}

	/**
	 * 获得邮件的收件人，抄送，和密送的地址和姓名，根据传递的参数 "to"----收件人 "cc"---抄送 "bcc"---密件抄送
	 * 
	 * @param mimeMessage
	 * @param type
	 * @return String
	 * @exception Exception
	 */
	private String getMailAddress(MimeMessage mimeMessage, String type) throws Exception {
		String mailaddr = "";
		String addtype = type.toUpperCase();
		InternetAddress[] address = null;
		if (addtype.equals("TO") || addtype.equals("CC") || addtype.equals("BCC")) {
			if (addtype.equals("TO")) {
				address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.TO);
			} else if (addtype.equals("CC")) {
				address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.CC);
			} else {
				address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.BCC);
			}
			if (address != null) {
				for (int i = 0; i < address.length; i++) {
					String email = address[i].getAddress();
					if (email == null) {
						email = "";
					} else {
						email = MimeUtility.decodeText(email);
					}
					String personal = address[i].getPersonal();
					if (personal == null) {
						personal = "";
					} else {
						personal = MimeUtility.decodeText(personal);
					}
					String compositeto = personal + "<" + email + ">";
					mailaddr += ("," + compositeto);
				}
				mailaddr = mailaddr.substring(1);
			}
		} else {
			throw new Exception("Error emailaddr type!");
		}
		return mailaddr;
	}

	/**
	 * 判断此邮件是否包含附件
	 * 
	 * @param part
	 * @return boolean
	 * @exception Exception
	 */
	private boolean isContainAttach(Part part) throws Exception {
		boolean attachflag = false;
		if (part.isMimeType("multipart/*")) {
			Multipart mp = (Multipart) part.getContent();
			for (int i = 0; i < mp.getCount(); i++) {
				BodyPart mpart = mp.getBodyPart(i);
				String disposition = mpart.getDisposition();
				if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT)) || (disposition.equals(Part.INLINE)))) {
					attachflag = true;
				} else if (mpart.isMimeType("multipart/*")) {
					attachflag = isContainAttach((Part) mpart);
				} else {
					String contype = mpart.getContentType();
					if (contype.toLowerCase().indexOf("application") != -1 || contype.toLowerCase().indexOf("name") != -1) {
						attachflag = true;
					}
				}
			}
		} else if (part.isMimeType("message/rfc822")) {
			attachflag = isContainAttach((Part) part.getContent());
		}
		return attachflag;
	}

	/**
	 * 保存附件
	 * 
	 * @param part
	 * @exception Exception
	 */
	@Transactional
	private void saveAttachMent(Part part) throws Exception {
		String fileName = "";
		if (part.isMimeType("multipart/*")) {
			Multipart mp = (Multipart) part.getContent();
			for (int i = 0; i < mp.getCount(); i++) {
				BodyPart mpart = mp.getBodyPart(i);
				String disposition = mpart.getDisposition();
				if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT)) || (disposition.equals(Part.INLINE)))) {
					fileName = mpart.getFileName();
					if (fileName!=null&&((fileName.toLowerCase().indexOf("?gb") != -1) || (fileName.toLowerCase().indexOf("gbk") != -1)|| (fileName.toLowerCase().indexOf("?utf-8") != -1))) {
						fileName = MimeUtility.decodeText(fileName);
					}
					saveFile(fileName, mpart.getInputStream());
				} else if (mpart.isMimeType("multipart/*")) {
					saveAttachMent(mpart);
				} else {
					fileName = mpart.getFileName();
					if (fileName != null) {
						fileName = MimeUtility.decodeText(fileName);
						saveFile("Screenshot.png", mpart.getInputStream());//截图生成附件
					}
				}
			}
		} else if (part.isMimeType("message/rfc822")) {
			saveAttachMent((Part) part.getContent());
		}
	}

	/**
	 * 【真正的保存附件到指定目录里】
	 * 
	 * @param fileName
	 * @param in
	 *            InputStream
	 * @exception Exception
	 */
	@Transactional
	private void saveFile(String fileName, InputStream in) throws Exception {
		// 保存附件的路径和真实附件名
		Attachment attachment = new Attachment();
		if(fileName==null ){
			fileName = new Date().getTime() +"";
		}
		attachment.setAttachmentName(fileName);
		if (fileName.indexOf(".") != -1) {
			// 自定义文件名
			fileName = new Date().getTime() + fileName.substring(fileName.indexOf("."));
		}else{
			fileName = new Date().getTime() +"";
		}
		String fileFolder = TimeUtils.format(new Date(),FILENAME_PATTERN);
		attachment.setUrl(fileFolder + File.separator + fileName);
		attachments.add(attachment);
		String osName = System.getProperty("os.name");
		String storedir = getAttachPath();
		if (osName == null) {
			osName = "";
		}
		if ((storedir == null) || storedir.equals("")) {
			if (osName.toLowerCase().indexOf("win") != -1) {
				storedir = "c:\\tmp";
			} else {
				storedir = "/tmp";
			}
		}
		File storefile = new File(storedir + File.separator + fileName);
		BufferedOutputStream bos = null;
		BufferedInputStream bis = null;
		try {
			bos = new BufferedOutputStream(new FileOutputStream(storefile));
			bis = new BufferedInputStream(in);
			int c;
			while ((c = bis.read()) != -1) {
				bos.write(c);
				bos.flush();
			}
		} catch (Exception exception) {
			LOGGER.error(exception);
			throw new Exception("文件保存失败!");
		} finally {
			if (bos != null) {
				bos.close();
			}
			if (bis != null) {
				bis.close();
			}
		}
	}

	/**
	 * 获取邮件标题
	 * 
	 * @param mimeMessage
	 * @return String
	 * @exception MessagingException
	 */
	@Transactional
	public String getSubject(MimeMessage mimeMessage) throws MessagingException {
		String subject = mimeMessage.getSubject();
		try {
			if (subject != null) {
				String[] str = mimeMessage.getHeader("Subject");
				if (str[0].indexOf("=") > -1) {
					subject = MimeUtility.decodeText(mimeMessage.getSubject());
				} else {
					subject = new String(subject.getBytes("iso-8859-1"));
				}
			}
		} catch (Exception exce) {
			LOGGER.error(exce);
		}
		return subject;
	}

	/**
	 * get ComparisonAndTerm
	 * 
	 * @param emailMessage
	 * @return SearchTerm
	 */
	private SearchTerm getComparisonAndTerm(EmailMessage emailMessage) {
		Date startDate = TimeUtils.parse("1985-01-01 00:00:00",TimeUtils.DATETIME_PATTERN);
		if (emailMessage != null && emailMessage.getReceiveDate() != null)
			startDate = emailMessage.getReceiveDate();
		// 搜索上次最后收到的时间到现在收到时间的邮件
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DAY_OF_WEEK, calendar.get(Calendar.DAY_OF_WEEK - (Calendar.DAY_OF_WEEK - 1)) - 1);
		SearchTerm comparisonTermGe = new SentDateTerm(ComparisonTerm.GT, startDate);
		SearchTerm comparisonTermLe = new SentDateTerm(ComparisonTerm.LE, new Date());
		SearchTerm comparisonAndTerm = new AndTerm(comparisonTermGe, comparisonTermLe);
		return comparisonAndTerm;
	}

	/**
	 * set EmailMessageDTO
	 * @param message
	 * @param dto
	 * @return EmailMessageDTO
	 * @throws MessagingException
	 */
	private EmailMessageDTO mimeMessageToEmailMessageDTO(MimeMessage message, String serverEmailAddres) throws MessagingException {
		String _subject = message.getSubject();
		String _content = getBodyText();
		InternetAddress[] address = (InternetAddress[]) message.getFrom();
		String _form = address[0].getAddress();
		EmailMessageDTO emailMessageDTO = new EmailMessageDTO();
		emailMessageDTO.setSubject(_subject);
		emailMessageDTO.setContent(_content);
		emailMessageDTO.setFromUser(_form);
		
		// 保存邮件信息
		Long mailId = saveEmailMessages(mime2Entity(message, "INBOX", serverEmailAddres));
		// 取得邮件ID
		emailMessageDTO.setEmailMessageId(mailId);
		return emailMessageDTO;
	}

	/**
	 * 接收邮件
	 * @param dto 连接邮件服务器信息
	 * @return 返回邮件集合
	 */
	@Transactional
	public List<EmailMessageDTO> receiveMail() {
		EmailServerDTO emailServerDTO=emailServerService.findReceiveEmail();
		if("Receive_exchange".equals(emailServerDTO.getEmailType())||"exchange".equals(emailServerDTO.getEmailType())){
			if(webDavService.emailConnTest(emailServerDTO)){//连接成功开始获取
				try {
					return webDavService.getInboxMail();
				} catch (Exception e) {
					throw new ApplicationException("ERROR_SCANEMAILMESSAGE\n\nExchange Scan Failure");
				}
			}else{
				throw new ApplicationException("ERROR_SCANEMAILMESSAGE\n\nExchange Conn Test Failure");
			}
		}else{
			EmailConnectionDTO connectionDTO=new EmailConnectionDTO();
//			connectionDTO.setSmtphost( emailServerDTO.getSmtpServerAddress(  ) );
//			connectionDTO.setSmtpport( Integer.parseInt( emailServerDTO.getSmtpServerPort(  ) ) );
			connectionDTO.setPop3host( emailServerDTO.getPop3ServerAddress(  ) );
			connectionDTO.setPop3port( Integer.parseInt( emailServerDTO.getPop3ServerPort(  ) ) );
			connectionDTO.setUsername( emailServerDTO.getUserName(  ) );
			connectionDTO.setPassword( emailServerDTO.getPassword(  ) );
			//连接测试
			int errorCode = emailConnTest( connectionDTO );
			if(errorCode==0){//准确无误，开始扫描邮箱，准备转换请求
				return this.getInboxMail();
			}else{
				throw new ApplicationException("ERROR_SCANEMAILMESSAGE\n\nConn Test Failure");
			}
			
		}
		
	}
	@Transactional
	private List<EmailMessageDTO> getInboxMail(){
		EmailServerDTO emailServerDTO=emailServerService.findReceiveEmail();
		List<EmailMessageDTO> ems = new ArrayList<EmailMessageDTO>();
		Properties props = setPopProperties(emailServerDTO.getPop3ServerAddress(), Integer.parseInt(emailServerDTO.getPop3ServerPort()));
		Session session = Session.getInstance(props, null);
		Store store = null;
		Message[] messages;
		try {
			store = session.getStore("pop3");
			store.connect(emailServerDTO.getUserName(), emailServerDTO.getPassword());
			Folder folder = store.getFolder("INBOX");
			folder.open(Folder.READ_ONLY);
			//获取系统中最后保存的邮件信息
			EmailMessage emailMessage = emailDAO.findLastestReceiveDate(emailServerDTO.getUserName());
			messages = reverse(folder.search(getComparisonAndTerm(emailMessage)));
			if(messages!=null && messages.length>0){
				int j=messages.length-1;
				for (int i = j; i >=0; i--) {
					MimeMessage message = (MimeMessage) messages[i];
					// 截取数据库没有的数据进行保存
					if (message != null) {
						 // 判断是否open
						if (message.getFolder()!=null && !message.getFolder().isOpen()){
							message.getFolder().open(Folder.READ_WRITE); // 如果close，就重新open
						}
						// 当解析邮件内容出错时，跳出本次循环
						try {
							this.getMailContent(message);
						} catch (Exception e) {
							LOGGER.error(e);
							continue;
						}
						EmailMessageDTO emailMessageDTO = mimeMessageToEmailMessageDTO(message, emailServerDTO.getUserName());
						ems.add(emailMessageDTO);
						
					}
				}
			}
			return ems;
		} catch (Exception e) {
			LOGGER.error(e);
			throw new ApplicationException("ERROR_SCANEMAILMESSAGE" + e, e);
		} finally {
			if (null != store && store.isConnected()) {
				try {
					store.close();
				} catch (MessagingException e) {
					LOGGER.error(e);
				}
			}
		}
	}
	/**
	 * 扫描收件箱的邮件信息
	 * 
	 * @param dto
	 *            EmailConnectionDTO
	 * @return boolean
	 */
	@Transactional
	private boolean getReceiveEmailMessage(EmailConnectionDTO dto) {
		Properties props = setPopProperties(dto.getPop3host(), dto.getPop3port());
		Session session = Session.getInstance(props, null);
		Store store = null;
		Message[] messages;
		try {
			store = session.getStore("pop3");
			store.connect(dto.getUsername(), dto.getPassword());
			Folder folder = store.getFolder("INBOX");
			folder.open(Folder.READ_ONLY);
			messages = reverse(folder.getMessages());
			EmailMessage emailMessage = emailDAO.findLastestReceiveDate(dto.getUsername());
			for (int i = 0; i < messages.length; i++) {
				MimeMessage message = (MimeMessage) messages[i];
				if (!message.getFolder().isOpen()) {// 判断是否open
					message.getFolder().open(Folder.READ_WRITE); // 如果close，就重新open
				}
				// 截取数据库没有的数据进行保存
				if ((emailMessage != null) && (message.getSentDate() != null)) {
					if (message.getSentDate().after(emailMessage.getReceiveDate())) {
						saveEmailMessages(this.mime2Entity(message, "INBOX", dto.getUsername()));
					}
				} else {
					saveEmailMessages(this.mime2Entity(message, "INBOX", dto.getUsername()));
				}
			}
			return true;
		} catch (Exception e) {
			LOGGER.error(e);
			throw new ApplicationException("ERROR_SCANEMAILMESSAGE\n" + e, e);
		} finally {
			if (null != store && store.isConnected()) {
				try {
					store.close();
				} catch (MessagingException e) {
					LOGGER.error(e);
				}
			}
		}
	}

	/**
	 * 扫描邮箱收件信息并保存入数据库
	 * 
	 * @param dto
	 *            EmailConnectionDTO
	 * @return boolean
	 */
	@Transactional
	public boolean saveReceiveMessages(EmailConnectionDTO dto) {
		return this.getReceiveEmailMessage(dto);
	}

	/**
	 * 将entity EmailMessage和affachment保存入数据库
	 * 
	 * @param emailMessage
	 *            EmailMessage
	 * @return EmailMessageId
	 */
	@Transactional
	public Long saveEmailMessages(EmailMessage emailMessage) {
		emailMessage.setSubject(FilterXssUtils.string_ecode(emailMessage.getSubject()));
		emailDAO.save(emailMessage);
		return emailMessage.getEmailMessageId();
	}

	/**
	 * 邮件分页查询
	 * 
	 * @param dto
	 *            查询条件DTO
	 * @param start
	 *            查询第几页
	 * @param limit
	 *            每页行数
	 * @param sidx
	 * @param sord
	 * @return PageDTO
	 */
	@SuppressWarnings("unchecked")
	@Transactional
	public PageDTO getEmailMessage(EmailMessageQueryDTO dto, int start, int limit, String sidx, String sord) {
		PageDTO p = emailDAO.findPager(dto, start, limit, sidx, sord);
		List<EmailMessage> entities = (List<EmailMessage>) p.getData();
		List<EmailMessageDTO> dtos = new ArrayList<EmailMessageDTO>(entities.size());
		Set<String> emails = new HashSet<String>();
		String[] emailStr = null;
		Map<String, String> map = new HashMap<String, String>();
		// 得到要查询的邮件地址
		for (EmailMessage entity : entities) {
			emails.add(strGet(entity.getFromUser()));// 发邮地址
			//emails.add(strGet(entity.getToUser()));// 接收地址
		}
		if (emails != null) {
			emailStr = emails.toArray(new String[emails.size()]);
			map = userInfoService.findUserByEmail(emailStr);
		}
		for (EmailMessage entity : entities) {
			EmailMessageDTO adto = this.entity2Dto(entity);
			if (map != null && map.get(strGet(entity.getFromUser())) != null) {
				adto.setFromUser(adto.getFromUser() + "[" + map.get(strGet(adto.getFromUser())) + "]");
			}
			adto.setContent("");
			dtos.add(adto);
		}
		p.setData(dtos);
		return p;
	}

	/**
	 * 字段串转换
	 * 
	 * @param str
	 * @return String
	 */
	private String strGet(String str) {
		String result = str;
		if (str != null&&str.indexOf("<") > -1) {
			result = str.substring(str.indexOf("<") + 1, str.indexOf(">"));
		}
		return result;
	}

	/**
	 * 根据ID查找邮件信息.
	 * 
	 * @param id
	 *            Long 编号
	 * @return EmailMessageDTO 邮件信息DTO
	 */
	@Transactional
	public EmailMessageDTO findById(Long id) {
		EmailMessage emailMessage = emailDAO.findById(id);
		EmailMessageDTO emailMessageDTO = new EmailMessageDTO();
		emailMessageDTO = this.entity2Dto(emailMessage);
		return emailMessageDTO;
	}

	/**
	 * 删除邮件信息
	 * 
	 * @param ids
	 */
	@Transactional
	public void deleteEmailMessage(Long[] ids) {
		emailDAO.deleteByIds(ids);
	}

	/**
	 * 根据登录帐号发送邮件
	 * 
	 * @param loginName
	 * @param title
	 * @param content
	 * @return boolean
	 */
	public boolean sendMailByLoginName(String loginName, String title, String content) {
		boolean result = false;
		EmailDTO emailDTO = new EmailDTO();
		if (StringUtils.hasText(loginName)) {
			User user = userDAO.findUniqueBy("loginName", loginName);
			if (user != null && StringUtils.hasText(user.getEmail())) {
				List<String> toEmail = new ArrayList<String>();
				toEmail.add(user.getEmail());
				emailDTO.setTo(toEmail);
				emailDTO.setSubject(title);
				emailDTO.setContent(content);
				result = this.sendMail(emailDTO);
			}
		}
		return result;
	}

	/**
	 * 赋值EmailConnectionDTO
	 * 
	 * @param emailConnectionDto
	 * @return EmailConnectionDTO
	 */
	public EmailConnectionDTO assignmentEmailServerDTO(EmailConnectionDTO emailConnectionDto) {
		EmailServerDTO emailServerDTO = emailServerService.findEmail();
		if (emailServerDTO != null) {
			if (StringUtils.hasText(emailServerDTO.getSmtpServerPort())) {
				emailConnectionDto.setSmtpport(Integer.parseInt(emailServerDTO.getSmtpServerPort()));
			}
			emailConnectionDto.setSmtphost(emailServerDTO.getSmtpServerAddress());
			if (StringUtils.hasText(emailServerDTO.getPop3ServerPort())) {
				emailConnectionDto.setPop3port(Integer.parseInt(emailServerDTO.getPop3ServerPort()));
			}
			emailConnectionDto.setPop3host(emailServerDTO.getPop3ServerAddress());
			emailConnectionDto.setUsername(emailServerDTO.getUserName());
			emailConnectionDto.setPassword(emailServerDTO.getPassword());
		}
		return emailConnectionDto;
	}
	/**
     * 连接测试，包含普通邮件及Exchange邮件的测试方法；
     * @param emailConnectionDto
     * @return
     */
	public int testEmailConn(EmailConnectionDTO emailConnDto,EmailServerDTO emailServerDTO) {
		if (emailServerDTO == null) {
			emailServerDTO = emailServerService.findEmail();
		}
		int result = FAIL_CONN_POP3ANDSMTP;//先设置为均失败
		int type = emailServerDTO.getServerEmailType();
		if (emailServerDTO != null && type != EmailServerDTO.EMAIL_TYPE_NONE) {
			if ( type == EmailServerDTO.EMAIL_TYPE_EXCHANGE) {// exchange邮件服务器
				boolean r = webDavService.emailConnTest(emailServerDTO);
				result = r ? SUCESS_CONN_ALL : FAIL_CONN_POP3ANDSMTP;
			} else {// 普通邮件服务器
				emailConnDto = assignmentEmailServerDTO(emailConnDto);
				result = emailConnTest(emailConnDto);
			}
		}
		return result;
	}
	/**
     * 邮件测试，分为发送与接收测试，包含普通邮件及Exchange邮件的发送测试方法；
     * @param emailConnectionDto
     * @param isSend 是否是发送测试；true发送测试，false接收测试
     * @return
     */
	public boolean testEmail(EmailServerDTO emailServerDTO,boolean isSend) {
		if (emailServerDTO == null) {
			emailServerDTO = emailServerService.findEmail();
		}
		boolean result = false;//先设置为失败
		if (emailServerDTO != null ) {
			int type = emailServerDTO.getServerEmailType() ;
			if ( type == EmailServerDTO.EMAIL_TYPE_EXCHANGE) {// exchange邮件服务器
				result = webDavService.emailConnTest(emailServerDTO);
			} else if ( type == EmailServerDTO.EMAIL_TYPE_NORMAL){// 普通邮件服务器
				EmailConnectionDTO emailConnDto = new EmailConnectionDTO();
				emailConnDto = setEmailConnectionDto(emailConnDto, emailServerDTO);
				emailConnDto = assignmentEmailServerDTO(emailConnDto);
				if (isSend) {
					result = sendEmailConnTest(emailConnDto);// 发送邮箱连接测试结果
				}else{
					result = receiveEmailConnTest(emailConnDto);// 接收邮箱连接测试结果
				}
			}
		}
		return result;
	}
}
